<?php
// 上传文件
namespace App\Http\Controllers\FileControllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use App\Models\File;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
use App\Models\DataTableModel\Folder;
use App\Models\DataTableModel\Icon;

class FileUploadController extends Controller
{
    public function upload(Request $request)
    {
        try {
            // 验证文件是否存在，并验证文件大小和类型
            // 给权限最多给到可查看，临时文件夹下的文件给只读权限  
            $validatedData = $request->validate([
                // 'file' => 'required|file|max:2048|mimes:xlsx,xlsm,csv,txt,pdf', // 假设最大2MB，并且只接受xlsx, xlsm, csv, txt, pdf文件  
                'file' => 'required|file',
            ]);
            dump($validatedData);
            // 获取上传文件
            $uploadedFile = $request->file('file');

            $user = Auth::user(); // 获取当前登录用户 
            // 获取当前用户id
            $userId = $user->id;

            // 在Folder数据表中通过用户id查找文件夹
            $userFolder = Folder::where('id', $user->id)->first();

            // 留一个初始用户文件夹传给下面变量使用
            $userFolder_old = $userFolder->folder_name;
            // 拼接文件夹路径
            $userFolder = 'UserNetworkDiskFile/' . $userFolder_old;
            dump($userFolder);
            // 检查用户文件夹是否存在，如果不存在则创建  
            if (!Storage::disk('public')->exists($userFolder)) {
                Storage::disk('public')->makeDirectory($userFolder);
            }

            // 获取上传文件的父文件信息
            $parentFolder = $request->input('targetFolder');
            dump($parentFolder);
            // 然后进行判断，如果值为/,则表示该目录上传到根目录下，如果为id，则表示上传到根目录其它的对应文件夹下（这个功能还没完善）
            // 进行判断  
            if ($parentFolder === '/') {
                // 如果值为/, 则表示该目录上传到根目录下  
                // 获取根目录文件夹的id（根据当前用户和parent_folder_id为null在folder表中查询）
                // 获取当前用户的根目录文件夹id,根据用户id和parent_folder_id字段为null查出用户根目录文件id,然后传入数据库
                $parentFolder = Folder::where('id', $userId)->whereNull('parent_folder_id')->value('folder_id');
                $rootFolderId = $parentFolder;
                dump($rootFolderId);
            }
            $folder = Folder::find($parentFolder);
            $folderName = $folder->folder_name;
            // 根据文件夹父文件夹id循环查找文件夹name，拼接，直到folder表中parent_folder_id=null

            // 拼接文件夹路径
            $folderPath = $folderName; // 用来存储完整路径的变量
            $pr_id = $folder->parent_folder_id; // 保存当前层级父文件夹id
            while ($pr_id != null) {
                $pr_folder = Folder::find($pr_id);
                $folderPath = $pr_folder->folder_name . '/' . $folderPath;
                $pr_id = $pr_folder->parent_folder_id;
            }
            $folderPath = '/' . $folderPath;
            $rootFolderId = $parentFolder;
            dump($folderPath);
            dump($rootFolderId);



            // 生成文件别名
            $fileName = time() . '_' . $uploadedFile->getClientOriginalName();

            // 获得文件类型,文件格式（大写）
            // 转化为大写（去掉小数点（获取文件后缀））
            $fileType = strtoupper(ltrim($uploadedFile->getClientOriginalExtension(), '.'));


            // 把文件类型转化为小写，供数据库查询使用
            $fileTypeStrtoupper = strtoupper(ltrim($uploadedFile->getClientOriginalExtension(), '.'));
            // 通过获取到的文件类型，在数据库中查询对应图标的id
            // 尝试根据文件类型进行模糊查询  
            $icon = Icon::where('icon_type', 'like', "%{$fileType}%")->first();
            // 初始化一个变量来存储图标ID  
            $iconId = null;
            if ($icon) {
                // 如果找到了匹配的图标，将其ID赋值给变量  
                $iconId = $icon->id;
            } else {
                // 如果没有找到，查询icon_type为"未知"的图标  
                $unknownIcon = Icon::where('icon_type', 'like', '%未知类型%')->first();
                if ($unknownIcon) {
                    // 如果找到了"未知"类型的图标，将其ID赋值给变量  
                    $iconId = $unknownIcon->id;
                }
            }



            // 获取文件大小，返回字节大小（单位：Bytes）
            $fileSize = $uploadedFile->getSize();

            // 获取文件名(不是获取文件别名)
            $fileNames = $uploadedFile->getClientOriginalName();
            // 获取要保存的文件路径（包括文件名）
            $userFolder = 'UserNetworkDiskFile' . $folderPath . '/' . $fileNames;
            dump($userFolder);
            // 存储文件到public磁盘  
            Storage::disk('public')->put($userFolder, file_get_contents($uploadedFile->getRealPath()));

            /**
             * 截取公共变量做全局变量
             * 储存之前，把公共部分删掉，用的时候再加上（两种方法：1.写一个变量，2.写到配置文件里面）
             * 本次我就放在session里面
             * 
             * 不做变量了，用的时候再重新获取一遍就行了
             * 
             */


            // 截取文件的相对路径（不包括'/storage/UserNetworkDiskFile/{{$userFolder_old}}'）
            $PublicVariables = '/storage/UserNetworkDiskFile/' . $userFolder_old;
            $userFolder = str_replace($PublicVariables, '', Storage::url($userFolder)); // 使用url访问文件  //储存之前，把公共部分删掉，用的时候再加上（两种方法：1.写一个变量，2.写到配置文件里面） 

            // 保存文件信息到数据库  
            $fileModel = new File;
            $fileModel->file_name = $uploadedFile->getClientOriginalName();
            $fileModel->file_path = $userFolder; // 裁剪之后的文件路径
            $fileModel->file_alias = 'alias_' . $fileName; // 文件别名 
            $fileModel->file_type = $fileType;  //文件类型
            $fileModel->file_size = $fileSize; // 文件大小
            $fileModel->file_parent_folder_id = $rootFolderId; // 上传文件的目标文件夹ID（父文件id）
            $fileModel->file_image_id = $iconId; // 图标ID
            // file_mod 在Laravel的文件系统中通常不需要设置，因为权限通常已经由文件系统处理  
            $fileModel->file_mod = 0644;
            $fileModel->user_id = $user->id; // 关联当前登录用户的ID  
            $fileModel->group_id = 1; // 默认组ID
            $fileModel->save(); // 保存 

            return response()->json(['success' => '文件上传成功.'], 200);
        } catch (ValidationException $e) {
            // 如果验证失败，返回错误信息  
            return response()->json(['error' => $e->errors()], 422);
        } catch (\Exception $e) {
            // 捕获其他异常并处理  
            if (config('app.debug')) {
                // 如果是开发环境，记录详细的异常信息并返回详细的错误给客户端  
                // \Log::error('Exception occurred: ' . $e->getMessage() . "\n" . $e->getTraceAsString());  
                return response()->json([
                    'error' => [
                        'message' => $e->getMessage(), // 具体的错误消息  
                        'file' => $e->getFile(), // 错误发生的文件  
                        'line' => $e->getLine(), // 错误发生的行号  
                        'trace' => explode("\n", $e->getTraceAsString()), // 完整的堆栈跟踪  
                    ],
                ], 500);
            } else {
                // 如果是生产环境，只记录异常信息并返回通用的错误给客户端  
                // \Log::error('Exception occurred: ' . $e->getMessage());  
                return response()->json(['error' => '服务器内部错误，请稍后再试'], 500);
            }
        }
    }
}
